package com.get.backstage.common.log.config;

import ch.qos.logback.classic.spi.CallerData;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.db.DBAppenderBase;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Controller;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

@Controller
public class LogDBAppender extends DBAppenderBase<ILoggingEvent> implements ApplicationContextAware {
    protected static final Method GET_GENERATED_KEYS_METHOD;
    private static ApplicationContext applicationContext;




    //插入sql
    protected String insertSQL;

//	// message 日志内容
//	static final int MESSAGE = 1;
//	// level_string
//	static final int LEVEL_STRING = 2;
//	// created_time 时间
//	static final int CREATE_TIME = 3;
//	// logger_name 全类名
//	static final int LOGGER_NAME = 4;


    // log_level 日志级别
    static final int LOG_LEVEL = 1;
    // log_method  日志的触发方法
    static final int LOG_METHOD = 2;
    // log_message 日志消息
    static final int LOG_MESSAGE = 3;
    // logback_log_code 日志编号
    static final int LOGBACK_LOG_CODE = 4;
    // 创建者
    static final int CREATOR = 5;
    // 创建时间
    static final int CREATE_TIME = 6;

    static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

    static {
        // PreparedStatement.getGeneratedKeys() method was added in JDK 1.4
        Method getGeneratedKeysMethod;
        try {
            // the
            getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
        } catch (Exception ex) {
            getGeneratedKeysMethod = null;
        }
        GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
    }

    @Override
    public void start() {
        // 将写好的sql语句赋值给insertSQL
        insertSQL = buildInsertSQL();
        super.start();
    }

    // 自己写新增sql语句
    private static String buildInsertSQL() {
        return "insert into user_logback_log"
                + "(log_level,log_method,log_message,logback_log_code,creator,create_time)"
                + " value "
                + "(?,?,?,?,?,?)";
    }

    @Override
    protected Method getGeneratedKeysMethod() {
        return GET_GENERATED_KEYS_METHOD;
    }

    @Override
    protected String getInsertSQL() {
        return insertSQL;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        LogDBAppender.applicationContext = applicationContext;
    }

    /**
     * 主要修改的方法
     *
     * @param stmt
     * @param event
     * @throws SQLException
     */
    private void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throws SQLException {
        //通过PreparedStatement 和 ILoggingEvent保存需要的内容

        stmt.setString(LOG_LEVEL, event.getLevel().levelStr);

        stmt.setString(LOG_METHOD, event.getLoggerName());

        stmt.setString(LOG_MESSAGE, event.getMessage());

        stmt.setString(LOGBACK_LOG_CODE, "USER_LOGBACK_LOG" + String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()));
        stmt.setString(CREATOR, "get_backstage_system");
        stmt.setString(CREATE_TIME, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));


    }

    @Override
    protected void subAppend(ILoggingEvent eventObject, Connection connection, PreparedStatement statement) throws Throwable {
        bindLoggingEventWithInsertStatement(statement, eventObject);
        int updateCount = statement.executeUpdate();
        if (updateCount != 1) {
            addWarn("Failed to insert loggingEvent");
        }
    }

    @Override
    protected void secondarySubAppend(ILoggingEvent eventObject, Connection connection, long eventId) throws Throwable {
        System.out.println("1");


    }
}